﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

/// <summary>
/// Summary description for PromoCal
/// </summary>
public class PromoCal : IComparable<PromoCal>
{
    public double Rating = 1;
    public double Score
    {
        get
        {
            return FinalPriceVat / Rating;
        }
    }
    public Package Package;
    public double VoicePrice;
    public double SmsPrice;
    public double MmsPrice;
    public double InternetPrice;

    public double FinalPriceVat
    {
        get
        {
            double allPrices = VoicePrice + SmsPrice + MmsPrice + InternetPrice;
            return Package.ProType.ToLower() == "postpaid" ? (allPrices * 1.07) : allPrices;
        }
    }
    private DataTable callingLog;
    public List<string> TopPhone = new List<string>();
    public string Provider = "";

    DataColumn cFromNo = new DataColumn("from_no", typeof(string));
    DataColumn cFromNet = new DataColumn("from_net", typeof(string));
    DataColumn cToNo = new DataColumn("to_no", typeof(string));
    DataColumn cToNet = new DataColumn("to_net", typeof(string));
    DataColumn cDate = new DataColumn("date", typeof(DateTime));
    DataColumn cTime = new DataColumn("time", typeof(double));
    DataColumn cHour = new DataColumn("hour", typeof(int));
    DataColumn cMin = new DataColumn("min", typeof(int));

    private double smsMonth = 0;
    private double mmsMonth = 0;
    private double internetHourMonth = 0;
    private double internetMbMonth = 0;

	public PromoCal(Package package, DataTable callingLog, string provider, double smsMonth, double mmsMonth, double internetHourMonth, double internetMbMonth)
	{
        this.Package = package;
        this.callingLog = callingLog;
        this.Provider = provider;

        cFromNo = callingLog.Columns["from_no"];
        cFromNet = callingLog.Columns["from_net"];
        cToNo = callingLog.Columns["to_no"];
        cToNet = callingLog.Columns["to_net"];
        cDate = callingLog.Columns["date"];
        cTime = callingLog.Columns["time"];
        cHour = callingLog.Columns["hour"];
        cMin = callingLog.Columns["min"];

        this.smsMonth = smsMonth;
        this.mmsMonth = mmsMonth;
        this.internetHourMonth = internetHourMonth;
        this.internetMbMonth = internetMbMonth;
	}

    public void CallCulate()
    {

        Dictionary<string, double> costs = new Dictionary<string, double>();

        var callingLinq = from myRow in callingLog.AsEnumerable()
                          select new
                          {
                              CallTo = myRow.Field<string>(cToNo),
                              NetTo = myRow.Field<string>(cToNet),
                              OnDate = myRow.Field<DateTime>(cDate),
                              AtTime = myRow.Field<double>(cTime),
                              InHour = myRow.Field<int>(cHour),
                              Minutes = myRow.Field<int>(cMin),
                          };

        int initDay = -1 * (callingLinq.Min(r => r.OnDate).Day -1);

        foreach (var x in callingLinq)
        {
            string yyyyMM = x.OnDate.AddDays(initDay).ToString("yyyyMM");
            if (!costs.ContainsKey(yyyyMM))
            {
                costs.Add(yyyyMM,0.0);
            }

            //int startMin = 0;
            int minLeft = x.Minutes;
            DateTime time = new DateTime(2000, 1, 1, x.OnDate.Hour, x.OnDate.Minute, 0);

            foreach (Calculation calc in Package.Calculation)
            {
                if (minLeft > 0)
                {
                    if (calc.Provider.ToLower() == "all" || calc.Provider.ToLower().Replace("rue", "") == x.NetTo.ToLower())
                    {

                        DateTime iCalc = GetHourMin(calc.StartTime);
                        DateTime fCalc = GetHourMin(calc.EndTime);
                        if (fCalc.Hour == 0)
                        {
                            fCalc = new DateTime(2000, 1, 1, 23, 59, 59);
                        }
                        else if (iCalc.Hour > fCalc.Hour)
                        {
                            fCalc = fCalc.AddDays(1);
                        }

                        if (time >= iCalc && time < fCalc || time >= iCalc.AddDays(-1) && time < fCalc.AddDays(-1))
                        {
                            int index = TopPhone.IndexOf(x.CallTo);

                            if ((index >= 0 && index < calc.TopNumber) || calc.TopNumber == 0)
                            {
                                int min = minLeft;
                                int timespan = calc.MinutesEnd - calc.MinutesStart;
                                if (min > timespan)
                                {
                                    min = timespan;
                                    minLeft -= timespan;
                                }
                                else
                                {
                                    minLeft = 0;
                                }

                                if (calc.PriceType.ToLower() == "whole")
                                {
                                    costs[yyyyMM] += calc.Price;
                                }
                                else
                                {
                                    costs[yyyyMM] += min * calc.Price;
                                }

                                time = time.AddMinutes(min);
                                time = time.AddDays(- time.Day + 1);
                            }
                        }
                    }
                }
                else
                {
                    break;
                }
            }
        }

        double maxMinPrice = 0;

        foreach (Calculation c in Package.Calculation)
        {
            if (c.PriceType.ToLower() == "permin")
            {
                if (c.Price > maxMinPrice)
                {
                    maxMinPrice = c.Price;
                }
            }
        }

        maxMinPrice = maxMinPrice <= 0 ? 1.5 : maxMinPrice;
        
        double sum = 0.0;

        foreach (string key in costs.Keys)
        {
            double cost = costs[key];
            if (cost - Package.FreeAmount > 0)
            {
                if (Package.FreeType.ToLower() == "time")
                {
                    cost = cost - Package.FreeAmount * maxMinPrice;
                }
                else
                {
                    cost = cost - Package.FreeAmount;
                }
            }
            else
            {
                cost = 0;
            }

            cost = cost < 0 ? 0 : cost;

            cost = cost + Package.InitPrice;
            sum += cost;
        }

        VoicePrice = Math.Round(sum / costs.Keys.Count(), 2);
        VoicePrice = VoicePrice < 0 ? 0 : VoicePrice;

        //Calc SMS
        SmsPrice = (smsMonth - Package.SmsFreeTimes) * Package.SmsPrice;
        SmsPrice = SmsPrice < 0 ? 0 : SmsPrice;

        //Calc MMS
        MmsPrice = (mmsMonth - Package.MmsFreeTimes) * Package.MmsPrice;
        MmsPrice = MmsPrice < 0 ? 0 : MmsPrice;

        //Calc internet
        //if (internetHourMonth <= 0)
        //{
        //    internetHourMonth = internetMbMonth / 10;
        //}
        //else if(internetMbMonth <=0)
        //{
        //    internetMbMonth = internetHourMonth * 10;
        //}

        if (Package.InternetType.ToLower() == "minutes")
        {
            InternetPrice = (internetHourMonth * 60 - Package.InternetFree) * Package.InternetPrice;
        }
        else
        {
            InternetPrice = (internetMbMonth- Package.InternetFree) * Package.InternetPrice;
        }

        InternetPrice = InternetPrice < 0 ? 0 : InternetPrice;
    }

    private DateTime GetHourMin(string hhmm)
    {
        
        int h = 0;
        int m = 0;

        try
        {
            string[] t = hhmm.Split(':');
            if (t.Length > 1)
            {
                h = int.Parse(t[0]);
                m = int.Parse(t[1]);
            }
            else if (t.Length == 1)
            {
                h = int.Parse(t[0]);
            }

            if (h >= 24)
            {
                h = 23;
                m = 59;
            }
        }
        catch
        {
        }
        
        return new DateTime(2000,1,1,h,m,0);
    }

    public int CompareTo(PromoCal other)
    {
        return this.Score.CompareTo(other.Score);
    }
}